﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FantastPlatform.Framework.IService;
using FantastPlatform.Framework.IModel;
using FantastPlatform.Framework.Model;
using FantastPlatform.Framework.Common;
using NHibernate.Criterion;
using NHibernate;
using FantastPlatform.Framework.Exception;
using System.Data;
using System.Data.SqlClient;

namespace FantastPlatform.Framework.Service
{
    public class RoleService : DataService<IRole, Role>, IRoleService
    {
        #region IRoleService 成员

        public bool CheckRight(IResource resource, IOperation operation)
        {
            throw new NotImplementedException();
        }

        public override object Create(IRole entity)
        {
            Check.Require<ObjectExistedException>(GetEntitiesByObject(new { Name = entity.Name }).SingleOrDefault<IRole>() == null,string.Format("角色：{0}已经存在！",entity.Name));
            return base.Create(entity);
        }
        public IList<IRole> LoadRolesNotExsit(string keywords, int userId, int page, int pageSize, out int totoalCount)
        {
            ICriteria criteria = Session.CreateCriteria(typeof(Role)).Add(Expression.Eq("Enable",true))
                .Add(Expression.Sql(string.Format("not exists(select * from User_UserRole where RoleId=this_.Id and UserId={0})",userId)));
            if (!string.IsNullOrEmpty(keywords))
                criteria.Add(Expression.Like("Name", keywords, MatchMode.Anywhere));
            ICriteria clone = criteria.Clone() as ICriteria;
            totoalCount = int.Parse(clone.SetProjection(Projections.RowCount()).UniqueResult().ToString());
            return criteria.SetFirstResult((page - 1) * pageSize).SetMaxResults(pageSize).List<IRole>();
        }

        public IList<IUser> GetUsers(int roleId, int page, int pageSize, out int totoalCount)
        {
            ICriteria criteria = Session.CreateCriteria(typeof(User)).Add(Expression.Eq("Enable",true))
                .CreateAlias("Roles", "r").Add(Expression.Eq("r.Id", roleId));
            ICriteria clone = criteria.Clone() as ICriteria;
            totoalCount = int.Parse(clone.SetProjection(Projections.RowCount()).UniqueResult().ToString());
            return criteria.SetFirstResult((page - 1) * pageSize).SetMaxResults(pageSize).List<IUser>();
        }

        public IList<IPermission> GetPermissions(int roleId, int page, int pageSize, out int totoalCount)
        {
            ICriteria criteria = Session.CreateCriteria(typeof(Permission)).Add(Expression.Eq("Enable",true))
                .CreateAlias("Roles", "r").Add(Expression.Eq("r.Id", roleId));
            ICriteria clone = criteria.Clone() as ICriteria;
            totoalCount = int.Parse(clone.SetProjection(Projections.RowCount()).UniqueResult().ToString());
            return criteria.SetFirstResult((page - 1) * pageSize).SetMaxResults(pageSize).List<IPermission>();
        }
        public void AddUsers(int id, IList<int> ids)
        {
            ITransaction tran = null;
            TransactionDelegate t = (ITransaction transaction) =>
                {
                    IRole role = Get(id);
                    Check.Require<ObjectNotExistedException>(role != null, "当前角色不存在！");
                    IDbCommand command = Session.Connection.CreateCommand();
                    transaction.Enlist(command);
                    DataTable dataTable = new DataTable();
                    dataTable.Columns.Add("UserId");
                    dataTable.Columns.Add("RoleId");
                    foreach (int i in ids)
                    {
                        if (!role.Users.Select(c => c.Id).Contains<int>(i))
                        {
                            Check.Require<ObjectNotExistedException>(Session.Get<User>(i) != null, string.Format("Id为{0}的用户不存在！", i));
                            DataRow dataRow = dataTable.NewRow();
                            dataRow["UserId"] = i;
                            dataRow["RoleId"] = id;
                            dataTable.Rows.Add(dataRow);
                        }
                    }
                    command.CommandText = "insert into User_UserRole(UserId,RoleId) values(@UserId,@RoleId)";
                    SqlParameter roleId = new SqlParameter();
                    roleId.ParameterName = "@RoleId";
                    roleId.SqlDbType = SqlDbType.Int;
                    roleId.SourceColumn = "RoleId";
                    SqlParameter userId = new SqlParameter();
                    userId.ParameterName = "@UserId";
                    userId.SqlDbType = SqlDbType.Int;
                    userId.SourceColumn = "UserId";
                    command.Parameters.Add(roleId);
                    command.Parameters.Add(userId);
                    SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();
                    sqlDataAdapter.InsertCommand = command as SqlCommand;
                    sqlDataAdapter.Update(dataTable);
                };
            ExecuteTransaction(t, tran);
        }


        public void RemoveUsers(int roleId, IList<int> userIds)
        {
            ITransaction tran = null;
            TransactionDelegate t = (ITransaction transaction) =>
                 {
                     IRole role = Get(roleId);
                     Check.Require<ObjectNotExistedException>(role != null, "当前角色不存在！");
                     foreach (int i in userIds)
                     {
                         Check.Require<ObjectNotExistedException>(Session.Get<User>(i) != null, string.Format("Id为{0}的用户不存在！", i));
                         Session.CreateSQLQuery(string.Format("delete from User_UserRole where RoleId={0} and UserId={1}", roleId, i)).ExecuteUpdate();
                     }
                 };
            ExecuteTransaction(t, tran);
        }

        public override void DeleteReally(List<int> ids)
        {
            List<string> tables=new List<string>();
            tables.Add("User_UserRole");
            tables.Add("User_RolePermission");
            base.DeleteReallyAndRelations(ids,tables);
        }
        public void UpdateRolePermissions(int roleId, IList<int> permissionIds)
        {
            Check.Require<ArgumentNullException>(Session.Get<Role>(roleId) != null, string.Format("ID为：{0}的角色不存在", roleId));
            ITransaction tran = null;
            TransactionDelegate t = (ITransaction transaction) =>
                {
                    Session.CreateSQLQuery(string.Format("delete from User_RolePermission where RoleId={0}", roleId)).ExecuteUpdate();
                    IDbCommand command = Session.Connection.CreateCommand();
                    transaction.Enlist(command);
                    DataTable dataTable = new DataTable();
                    dataTable.Columns.Add("RoleId");
                    dataTable.Columns.Add("PermissionId");
                    foreach (int permissionId in permissionIds)
                    {
                        Check.Require<ArgumentNullException>(Session.Get<Permission>(permissionId) != null, string.Format("ID为：{0}的角色不存在", permissionId));
                        DataRow dataRow = dataTable.NewRow();
                        dataRow["RoleId"] = roleId;
                        dataRow["PermissionId"] = permissionId;
                        dataTable.Rows.Add(dataRow);
                    }
                    command.CommandText = "insert into User_RolePermission(RoleId,PermissionId) values(@RoleId,@PermissionId)";
                    SqlParameter proleId = new SqlParameter();
                    proleId.ParameterName = "@RoleId";
                    proleId.SqlDbType = SqlDbType.Int;
                    proleId.SourceColumn = "RoleId";
                    SqlParameter PermissionId = new SqlParameter();
                    PermissionId.ParameterName = "@PermissionId";
                    PermissionId.SqlDbType = SqlDbType.Int;
                    PermissionId.SourceColumn = "PermissionId";
                    command.Parameters.Add(proleId);
                    command.Parameters.Add(PermissionId);
                    SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();
                    sqlDataAdapter.InsertCommand = command as SqlCommand;
                    sqlDataAdapter.Update(dataTable);
                };
            ExecuteTransaction(t, tran);
        }

        #endregion
    }
}
